package com.freewater.springboot.demo.core.resolvabletype.eg2;

import org.springframework.core.ResolvableType;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;

/**
 * 会用到VariableResolver
 */
public class Main {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        //BusinessImpl中没有字段list的声明
        //Field listField = BusinessImpl.class.getDeclaredField("list");
        /* 泛型字段：ParameterizedType */
        Field listField = Business.class.getDeclaredField("list");
        ResolvableType rt = ResolvableType.forField(listField);
        System.out.println(rt.getType()); // java.util.List<T>
        System.out.println(rt.getGeneric(0).getType()); // T
        // 没有VariableResolver，因此T这个TypeVariable没法解析到具体的Class
        System.out.println(rt.getGeneric(0).resolve()); // null
        // 要解析T的具体类型，必须指定listField所在抽象类的具体实现类
        rt = ResolvableType.forField(listField, BusinessImpl.class);
        System.out.println(rt.getType()); // java.util.List<T>
        System.out.println(rt.getGeneric(0).getType()); // T
        System.out.println(rt.getGeneric(0).resolve()); // class java.lang.String
        /* 泛型字段：TypeVariable */
        Field itemField = Business.class.getDeclaredField("item");
        rt = ResolvableType.forField(itemField);
        System.out.println(rt.getType()); // T
        System.out.println(rt.resolve()); // null
        //
        rt = ResolvableType.forField(itemField, BusinessImpl.class);
        System.out.println(rt.getType()); // T
        System.out.println(rt.resolve()); // class java.lang.String
        /* 泛型字段：GenericArrayType */
        Field arrayField = Business.class.getDeclaredField("array");
        rt = ResolvableType.forField(arrayField);
        System.out.println(rt.getType());// T[]
        System.out.println(rt.resolve());// null
        //
        rt = ResolvableType.forField(arrayField, BusinessImpl.class);
        System.out.println(rt.getType());// T[]
        System.out.println(rt.resolve());// class [Ljava.lang.String
        /* 泛型构造方法指定参数 */
        Constructor<?> constructor = Business.class.getDeclaredConstructors()[0];
        ResolvableType cpRt = ResolvableType.forConstructorParameter(constructor, 0);
        System.out.println(cpRt.getType());// java.util.List<T>
        System.out.println(cpRt.resolve());// interface java.util.List
        System.out.println(cpRt.getGeneric(0).getType());// T
        System.out.println(cpRt.getGeneric(0).resolve());// null
        //
        cpRt = ResolvableType.forConstructorParameter(constructor, 0, BusinessImpl.class);
        System.out.println(cpRt.getType());// java.util.List<T>
        System.out.println(cpRt.resolve());// interface java.util.List
        System.out.println(cpRt.getGeneric(0).getType());// T
        System.out.println(cpRt.getGeneric(0).resolve());// class java.lang.String
        /* 泛型方法指定参数 */
        Method addAllMethod = Business.class.getDeclaredMethod("addAll", Collection.class);
        ResolvableType mpRt = ResolvableType.forMethodParameter(addAllMethod, 0);
        System.out.println(mpRt.getType());// java.util.Collection<? extends T>
        System.out.println(mpRt.resolve());// interface java.util.Collection
        System.out.println(mpRt.getGeneric(0).getType());// ? extends T
        System.out.println(mpRt.getGeneric(0).resolve());// null
        //
        mpRt = ResolvableType.forMethodParameter(addAllMethod, 0, BusinessImpl.class);
        System.out.println(mpRt.getType());// java.util.Collection<? extends T>
        System.out.println(mpRt.resolve());// interface java.util.Collection
        System.out.println(mpRt.getGeneric(0).getType());// ? extends T
        System.out.println(mpRt.getGeneric(0).resolve());// class java.lang.String

        /* 泛型方法指定参数 */
        Method sortMethod = Business.class.getDeclaredMethod("sort", Comparable.class);
        ResolvableType mpRt2 = ResolvableType.forMethodParameter(sortMethod, 0);
        System.out.println(mpRt2.getType());// java.lang.Comparable<? super T>
        System.out.println(mpRt2.resolve());// interface java.lang.Comparable
        System.out.println(mpRt2.getGeneric(0).getType());// ? super T
        System.out.println(mpRt2.getGeneric(0).resolve());// null
        //
        mpRt2 = ResolvableType.forMethodParameter(sortMethod, 0, BusinessImpl.class);
        System.out.println(mpRt2.getType());// java.lang.Comparable<? super T>
        System.out.println(mpRt2.resolve());// interface java.lang.Comparable
        System.out.println(mpRt2.getGeneric(0).getType());// ? super T
        System.out.println(mpRt2.getGeneric(0).resolve());// class java.lang.String
    }
}
